"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * Base64字符串处理
 * 支持一般Base64的编码和解码
 * 支持符合RFC_4648标准中"URL and Filename Safe Alphabet"的URL安全Base64编解码
 * 支持中文字符的编解码(Unicode编码)
 */
const lowers = "abcdefghijklmnopqrstuvwxyz";
const uppers = lowers.toUpperCase();
const numbers = "0123456789";
const others = "+/";
const urls = "-_";
const b64Map = `${uppers}${lowers}${numbers}${others}`.split("");
const urlMap = `${uppers}${lowers}${numbers}${urls}`.split("");
/**编码转成二进制(unicode转binary) */
const _toBinary = (ascii) => {
    const binary = [];
    while (ascii > 0) {
        const b = ascii % 2;
        ascii = Math.floor(ascii / 2);
        binary.push(b);
    }
    binary.reverse();
    return binary;
};
/**二进制编码转成十进制(binary转unicode) */
const _toDecimal = (binary) => {
    let dec = 0;
    let p = 0;
    for (var i = binary.length - 1; i >= 0; --i) {
        var b = binary[i];
        if (b == 1)
            dec += Math.pow(2, p);
        ++p;
    }
    return dec;
};
/**转成n字节UTF8二进制 */
const _toUTF8Binary = (n, binaryArray) => {
    const mustLen = 8 - (n + 1) + (n - 1) * 6;
    const fatLen = binaryArray.length;
    let diff = mustLen - fatLen;
    while (--diff >= 0)
        binaryArray.unshift(0);
    const binary = [];
    let _n = n;
    while (--_n >= 0)
        binary.push(1);
    binary.push(0);
    let i = 0;
    const len = 8 - (n + 1);
    for (; i < len; ++i)
        binary.push(binaryArray[i]);
    for (let j = 0; j < n - 1; ++j) {
        binary.push(1);
        binary.push(0);
        let sum = 6;
        while (--sum >= 0)
            binary.push(binaryArray[i++]);
    }
    return binary;
};
/**字符串转成二进制列表 */
const _toBinaryArray = (str) => {
    let binaryArray = [];
    for (let i = 0, len = str.length; i < len; ++i) {
        const unicode = str.charCodeAt(i);
        const _tmpBinary = _toBinary(unicode);
        if (unicode < 0x80) {
            let _tmpdiff = 8 - _tmpBinary.length;
            while (--_tmpdiff >= 0)
                _tmpBinary.unshift(0);
            binaryArray = binaryArray.concat(_tmpBinary);
        }
        else if (unicode >= 0x80 && unicode <= 0x7ff) {
            binaryArray = binaryArray.concat(_toUTF8Binary(2, _tmpBinary));
        }
        else if (unicode >= 0x800 && unicode <= 0xffff) {
            //UTF-8 3byte
            binaryArray = binaryArray.concat(_toUTF8Binary(3, _tmpBinary));
        }
        else if (unicode >= 0x10000 && unicode <= 0x1fffff) {
            //UTF-8 4byte
            binaryArray = binaryArray.concat(_toUTF8Binary(4, _tmpBinary));
        }
        else if (unicode >= 0x200000 && unicode <= 0x3ffffff) {
            //UTF-8 5byte
            binaryArray = binaryArray.concat(_toUTF8Binary(5, _tmpBinary));
        }
        else if (unicode >= 4000000 && unicode <= 0x7fffffff) {
            //UTF-8 6byte
            binaryArray = binaryArray.concat(_toUTF8Binary(6, _tmpBinary));
        }
    }
    return binaryArray;
};
/**二进制列表转成字符串 */
const _toUnicodeStr = (binaryArray) => {
    let unicode;
    let unicodeBinary = [];
    let str = "";
    for (let i = 0, len = binaryArray.length; i < len;) {
        if (binaryArray[i] == 0) {
            unicode = _toDecimal(binaryArray.slice(i, i + 8));
            str += String.fromCharCode(unicode);
            i += 8;
        }
        else {
            let sum = 0;
            while (i < len) {
                if (binaryArray[i] != 1)
                    break;
                ++sum;
                ++i;
            }
            unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 1, i + 8 - sum));
            i += 8 - sum;
            while (sum > 1) {
                unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 2, i + 8));
                i += 8;
                --sum;
            }
            unicode = _toDecimal(unicodeBinary);
            str += String.fromCharCode(unicode);
            unicodeBinary = [];
        }
    }
    return str;
};
/**普通字符串编码成Base64字符串 */
const _encode = (str, isUrl = false) => {
    const base64_Index = [];
    const binaryArray = _toBinaryArray(str);
    const dictionary = isUrl ? urlMap : b64Map;
    let extra_Zero_Count = 0;
    for (let i = 0, len = binaryArray.length; i < len; i += 6) {
        const diff = i + 6 - len;
        if (diff == 2) {
            extra_Zero_Count = 2;
        }
        else if (diff == 4) {
            extra_Zero_Count = 4;
        }
        let _tmpExtra_Zero_Count = extra_Zero_Count;
        while (--_tmpExtra_Zero_Count >= 0)
            binaryArray.push(0);
        base64_Index.push(_toDecimal(binaryArray.slice(i, i + 6)));
    }
    let base64 = "";
    for (let i = 0, len = base64_Index.length; i < len; ++i) {
        base64 += dictionary[base64_Index[i]];
    }
    for (let i = 0, len = extra_Zero_Count / 2; i < len; ++i) {
        base64 += "=";
    }
    return base64;
};
/**Base64字符串解码成普通字符串 */
const _decode = (_base64Str, isUrl = false) => {
    const _len = _base64Str.length;
    let extra_Zero_Count = 0;
    const dictionary = isUrl ? urlMap : b64Map;
    if (_base64Str.charAt(_len - 1) == "=") {
        if (_base64Str.charAt(_len - 2) == "=") {
            extra_Zero_Count = 4; //两个等号说明补了4个0
            _base64Str = _base64Str.substring(0, _len - 2);
        }
        else {
            extra_Zero_Count = 2; //一个等号说明补了2个0
            _base64Str = _base64Str.substring(0, _len - 1);
        }
    }
    let binaryArray = [];
    for (let i = 0, len = _base64Str.length; i < len; ++i) {
        const c = _base64Str.charAt(i);
        for (let j = 0, size = dictionary.length; j < size; ++j) {
            if (c == dictionary[j]) {
                const _tmp = _toBinary(j);
                const _tmpLen = _tmp.length;
                /*不足6位的补0*/
                if (6 - _tmpLen > 0) {
                    for (var k = 6 - _tmpLen; k > 0; --k) {
                        _tmp.unshift(0);
                    }
                }
                binaryArray = binaryArray.concat(_tmp);
                break;
            }
        }
    }
    if (extra_Zero_Count > 0) {
        binaryArray = binaryArray.slice(0, binaryArray.length - extra_Zero_Count);
    }
    return _toUnicodeStr(binaryArray);
};
/**Base64转换器 */
class MB64 {
    /**字符串编码成Base64 */
    static encode(str) {
        return _encode(str, false);
    }
    /**Base64解码成字符串 */
    static decode(str) {
        return _decode(str, false);
    }
    /**地址字符串编码成Base64 */
    static urlEncode(url) {
        return _encode(url, true);
    }
    /**Base64解码成地址字符串 */
    static urlDecode(url) {
        return _decode(url, true);
    }
}
exports.default = MB64;
